<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        background-color: white;
      }

      @keyframes ColorChange {
        0% {
          outline: 1px solid lightgreen;
        }

        50% {
          outline: 1px solid green;
        }

        1000% {
          outline: 1px solid lightgreen;
        }
      }

      svg {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate3d(-50%, -50%, 0);
        outline: 1px solid red;
        animation: ColorChange 500ms ease infinite;
        transition: all linear 300;
      }

      line,
      polyline,
      rect {
        stroke-linecap: round;
        stroke-linejoin: round;
      }
    </style>
  </head>

  <body>
    <svg id="clock"
         width="600"
         height="600"
         xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         preserveAspectRatio="xMinYMin meet"
         stroke-linecap="round"
         stroke-linejoin="round"
         viewBox="0 0 600 600">

      <!-- 第十四章 使用SVG DOM P198 -->
      <!--
        本章讲述了svg各元素（rect、ellipse、circlr等）的属性值的取值/设置值，和一些接口方法。
        和htmldom元素的获取方法一样，使用document.getElementById、document.querySelector等方法获取到元素的对象引用。
      -->
      <!--
        14.1 确定元素的属性值
          每个svg元素的属性值都有两个子属性，baseVal和animVal，animVal只读，动画产生时会创思更新始终代表当前属性值。
          baseVal和animVal 是包含自身数据的复杂对象，对长度和角度来说，baseVal.value 和 animVal.value 属性始终存储以用户单位保存的值（角度单位为度），而不管在设定属性时使用的是什么单位。
          baseVal和animVal 对象还包含不同单位之间进行转换的方法。

          通过 el.getAttribute("rx")获取到一个属性的对象后
            el.rx.baseVal.value 是 rx 被转换为用户单位之后的值。
            el.rx.baseVal.valueAsString 是完整的字符串，包含单位。
            el.ry.baseVal.valueInSpecifiedUnits 是数值类型的属性值，但是单位是设定属性时使用的单位。
            convertToSpecifiedUnits(unitConstant)方法可以用来转换单位（本例中转换为了em）。该方法并不直接返回任何值，而是会改变对象中的 valueAsString 和 valueInSpecifiedUnits 属性值。value 属性的单位始终是用户单位，不受影响。
      -->

      <!--
        14.2 接口方法。。。太多了，详见P203
      -->
    </svg>


    <!--
      14.3 使用ECMAScript/JavaScript创建SVG
    -->
    <script>
      let clock;
      function Init() {
        // 获取这个空svg元素
        clock = document.querySelector("#clock");
        let doc = document;
        let svgns = clock.namespaceURI;
        // 非必须，但在进行大量DOM操作之前暂停svg的更新可以提升在某些圆度其中的性能
        clock.suspendRedraw(1000);

        // 创建表盘
        const face = doc.createElementNS(svgns, "circle");
        face.cx.baseVal.value = 300;
        face.cy.baseVal.value = 300;
        face.r.baseVal.value = 300;
        face.style.cssText = `
          fill: white;
          stroke: black;
        `;
        clock.appendChild(face);
        // 创建小时识别组
        const ticks = clock.appendChild(doc.createElementNS(svgns, "g"));
        ticks.setAttribute("transform", "translate(300,300)");
        let tickMark;
        for (let i = 1; i <= 12; i++) {
          tickMark = doc.createElementNS(svgns, 'path');
          tickMark.setAttribute('d', "M295,0L300,-5L300,5z");
          tickMark.setAttribute('transform', `rotate(${30 * i})`);
          ticks.appendChild(tickMark);
        }
        // 创建时针
        const hours = clock.appendChild(doc.createElementNS(svgns, "g"));
        hours.style.cssText = `
          stroke: black;
          stroke-width: 5px;
          stroke-linecap: round;
        `;
        const hourHand = hours.appendChild(doc.createElementNS(svgns, "path"));
        hourHand.id = "hour";
        hourHand.setAttribute("d", "M300,300L300,150");
        hourHand.setAttribute("transform", "rotate(0,300,300)");

        // 创建分针
        const mins = clock.appendChild(doc.createElementNS(svgns, "g"));
        mins.style.cssText = `
          stroke: green;
          stroke-width: 4px;
          stroke-linecap: round;
        `;
        const minHand = mins.appendChild(doc.createElementNS(svgns, "path"));
        minHand.id = "min";
        minHand.setAttribute("d", "M300,300L300,100");
        minHand.setAttribute("transform", "rotate(0,300,300)");

        // 创建秒针
        const secs = clock.appendChild(doc.createElementNS(svgns, "g"));
        secs.style.cssText = `
          stroke: red;
          stroke-width: 2px;
          stroke-linecap: round;
        `;
        const secHand = secs.appendChild(doc.createElementNS(svgns, "path"));
        secHand.id = "sec";
        secHand.setAttribute("d", "M300,300L300,50");
        secHand.setAttribute("transform", "rotate(0,300,300)");

        // 创建中心元素
        const knob = doc.createElementNS(svgns, "circle");
        knob.setAttribute("cx", "300");
        knob.setAttribute("cy", "300");
        knob.setAttribute("r", "6");
        knob.style.setProperty("fill", "red", null);
        clock.appendChild(knob);
      }

      let hourHand;
      let minHand;
      let secHand;
      let secTransform;
      let minTransform;
      let hourTransform;
      const secPerMinute = 60;
      const secPerHour = 60 * 60;
      const secPer12Hours = 60 * 60 * 12;

      function InitData() {
        // 获取元素引用
        hourHand = document.querySelector("#hour");
        minHand = document.querySelector("#min");
        secHand = document.querySelector("#sec");
        // 获取代表当前旋转的变量矩阵SVGTransform对象rotate(0,300,300)
        secTransform = secHand.transform.baseVal.getItem(0);
        minTransform = minHand.transform.baseVal.getItem(0);
        hourTransform = hourHand.transform.baseVal.getItem(0);
        updateClock();
      }
      function updateClock() {
        // 获取系统时间
        const date = new Date();
        // 计算从0点开始过去的秒数
        const time =
          date.getMilliseconds() / 1000 +
          date.getSeconds() +
          date.getMinutes() +
          date.getHours() * 60 * 60;
        // 计算旋转角度
        const s = 360 * (time % secPerMinute) / secPerMinute;
        const m = 360 * (time % secPerHour) / secPerHour;
        const h = 360 * (time % secPer12Hours) / secPer12Hours;
        secTransform.setRotate(s, 300, 300);
        minTransform.setRotate(m, 300, 300);
        hourTransform.setRotate(h, 300, 300);
        window.requestAnimationFrame(updateClock);
      }
      Init();
      InitData();


      // 也可以使用D3.js、Raphaël、Snap.svg等等第三方库来简化代码
    </script>


    <script>
      const ele = document.querySelector("#xxx");
      let n = 0;
      function Renderer() {
        n++;
        if (n >= 360) n = 0;
        window.requestAnimationFrame(Renderer);
      }
      Renderer();
    </script>
  </body>

</html>
